using UnityEngine;
using System.Collections;
using System.Collections.Generic;

public class Enemy : MonoBehaviour 
{
    protected Transform enemyTransform;
    public GameObject colliderGO;
    public GameObject colliderConeEnd;
    public GameObject colliderConeStart;
    public GameObject textureCone;
    public EnemyCurve curve;

	public Texture texShowPlayer;
	public Texture texShowTrap;
	public Texture texWalk;
	public Texture texDead;

    protected Const.ENNEMY_TYPE type;

    private bool _alive;
    public bool Alive
    {
        get { return _alive; }
        set { _alive = value; }
    }

    private bool _launch;
    private Const.ENEMY_WAY _way;
    private Vector3 _savePos;
    private LevelManager _levelMgr;
	protected Const.ENEMY_STATUS status = Const.ENEMY_STATUS.FOLLOWING_PATH;
    private Move _playerMove;

    //features -> scale des bipolar

	// Use this for initialization
	protected void Start ()
    {
        _levelMgr = (LevelManager)FindObjectOfType(typeof(LevelManager));
		_playerMove = (Move)FindObjectOfType(typeof(Move));
		colliderGO.rigidbody.isKinematic = true;
	}

	private Const.ENEMY_STATUS prevState = Const.ENEMY_STATUS.SHOWING_PLAYER;

	// Update is called once per frame
	protected void Update ()
    {
        //Look next position on curve
        if (_launch && _alive && status == Const.ENEMY_STATUS.FOLLOWING_PATH)
        {
            Vector3 diff = this.transform.position - _savePos;

            this.transform.LookAt(this.transform.position + diff);

            _savePos = this.transform.position;
        }

		if (status != prevState)
		{
			Anim anim;
			switch (status)
			{
				case Const.ENEMY_STATUS.FOLLOWING_PATH:
					anim = this.GetComponent<Anim>();
					anim.speed = 0.1f;
					anim.resetTimer(texWalk, 12);
					break;
				case Const.ENEMY_STATUS.SHOWING_PLAYER:
					anim = this.GetComponent<Anim>();
					anim.resetTimer(texShowPlayer, 1);
					break;
				case Const.ENEMY_STATUS.SHOWING_TRAP:
					anim = this.GetComponent<Anim>();
					anim.resetTimer(texShowTrap, 1);
					break;
				case Const.ENEMY_STATUS.DEAD:
					anim = this.GetComponent<Anim>();
					anim.resetTimer(texDead, 1);
					break;
			}

            prevState = status;
		}
	}

    //Set enemy attribute
    public void createEnnemy(EnemyCurve pCurve, Const.ENNEMY_TYPE pType, string pName = "")
    {
        curve = pCurve;
        type = pType;
        enemyTransform = this.transform;
        if (pName.Length > 0)
            name = pName;
        
        
        //Launch Move
        this.animation.AddClip(curve.GetAnimation(), "Move");
        this.animation.Play("Move");
        this.animation.wrapMode = WrapMode.Loop;

        //Set Way
        _way = Const.ENEMY_WAY.FORWARD;
        _savePos = this.transform.position;

        //Tag
        this.gameObject.layer = Const.LAYER_ENEMY;

        //Rigidbody
        colliderGO.AddComponent<Rigidbody>();
        colliderGO.rigidbody.useGravity = false;

        _launch = true;
        _alive = true;
    }

    private void Dead()
	{
		status = Const.ENEMY_STATUS.DEAD;
		var anim = this.GetComponent<Anim>();
		anim.resetTimer(texDead, 1);

        this.animation.Stop();
        colliderGO.collider.enabled = false;
        _alive = false;

        if (_levelMgr.IsStageClear())
            StartCoroutine(AnimateAndEnd(true));

        colliderConeEnd.renderer.enabled = false;
        colliderConeStart.renderer.enabled = false;
        textureCone.renderer.enabled = false;

        SoundManager.Instance.PlayFX("enemyDie");
        SoundManager.Instance.PlayFX("miniWin");
    }

	IEnumerator AnimateAndEnd(bool win)
	{
		Debug.Log("Et c'est le win !");
		var player = (Move) FindObjectOfType(typeof (Move));
		player.enabled = false;
		player.GetComponent<Anim>().resetTimer(win?player.texWin : player.texSpotted, 1);
		yield return new WaitForSeconds(1.0f);
		_levelMgr.EndStage(win);
	}
    /*
	private void DeactivateTrap(GameObject trap)
	{
		//play animation ?
		Destroy(trap);
	}*/

    //Trap Collider
    void OnTriggerEnter(Collider obj)
    {
        if (obj.gameObject.layer == Const.LAYER_TRAP)
        {
	        var trap = obj.GetComponent<Trap>();
	        switch (trap.typeTrap)
            {
                case Const.TRAP_TYPE.BILLE :
                    BilleEffect((Bille)trap);
                    break;
            }
        }
    }

    public void ReparePlayer()
    {
        this.animation.Stop();
    }

    //Bille Effect
    public void BilleEffect(Bille b)
    {
	    if (b.HasBeenSeen)
	    {
		    
	    }
	    else
	    {
            StartCoroutine(WaitForBilles());
		    
	    }
    }

    IEnumerator WaitForBilles()
    {
        this.transform.position = new Vector3(this.transform.position.x, this.transform.position.y + 10, this.transform.position.z);
        yield return new WaitForSeconds(0.2f);
        SoundManager.Instance.PlayFX("enemyFall");
        Dead();
    }

	//Firecracker effect
    public void FireCrackerEffect()
    {
        SoundManager.Instance.PlayFX("enemyScream");
        Dead();
    }

    //Stone Effect
    public void StoneEffect()
    {
        SoundManager.Instance.PlayFX("enemyHit");
        Dead();
    }

    //Scary Citrouille
    public void ScaryCitrouille()
    {
        SoundManager.Instance.PlayFX("enemyScream");
        Dead();
    }


    public bool TestRaycast(GameObject obj)
    {
        if (status == Const.ENEMY_STATUS.SHOWING_PLAYER)
            return false;       

        Quaternion orient = this.transform.rotation;
        this.transform.LookAt(new Vector3(obj.transform.position.x, this.transform.position.y, obj.transform.position.z));

        Ray ray = new Ray(this.transform.position, this.transform.forward);
        RaycastHit hit;
        float distanceObstacle = -1;
        if (Physics.Raycast(ray, out hit, 500000, 1<<0))
        {
            distanceObstacle = Vector3.Distance(hit.point, this.transform.position);
        }

        if (distanceObstacle == -1 || Vector3.Distance(obj.transform.position, this.transform.position) < distanceObstacle)
        {
            status = Const.ENEMY_STATUS.SHOWING_PLAYER;
            return true;
        }
        Physics.IgnoreLayerCollision(Const.LAYER_PLAYER, Const.LAYER_CONE_END);
        Physics.IgnoreLayerCollision(Const.LAYER_PLAYER, Const.LAYER_CONE_START);

        StartCoroutine(TryActivateCollider());

        this.transform.rotation = orient;
        return false;

    }

    IEnumerator TryActivateCollider()
    {
        yield return new WaitForSeconds(0.1f);

        Physics.IgnoreLayerCollision(Const.LAYER_PLAYER, Const.LAYER_CONE_END, false);
        Physics.IgnoreLayerCollision(Const.LAYER_PLAYER, Const.LAYER_CONE_START, false);

        if (colliderConeEnd.collider.bounds.Intersects(_playerMove.collider.bounds))
        {
            Physics.IgnoreLayerCollision(Const.LAYER_PLAYER, Const.LAYER_CONE_END, true);
            Physics.IgnoreLayerCollision(Const.LAYER_PLAYER, Const.LAYER_CONE_START, true);
            StartCoroutine(TryActivateCollider());
        }
        else if (colliderConeStart.collider.bounds.Intersects(_playerMove.collider.bounds))
        {
            Physics.IgnoreLayerCollision(Const.LAYER_PLAYER, Const.LAYER_CONE_END, true);
            Physics.IgnoreLayerCollision(Const.LAYER_PLAYER, Const.LAYER_CONE_START, true);
            StartCoroutine(TryActivateCollider());
        }

    }


    //Show Billes
    public void ShowTrap(GameObject trap)
    {
        if (status == Const.ENEMY_STATUS.SHOWING_TRAP)
            return;
        
        Quaternion orient = this.transform.rotation;
        this.transform.LookAt(new Vector3(trap.transform.position.x, this.transform.position.y, trap.transform.position.z));

        float distanceTrap = Vector3.Distance(trap.transform.position, this.transform.position);
        //TODO Raycast
        Vector3 dir = new Vector3(trap.transform.position.x - this.transform.position.x, 0, trap.transform.position.z - this.transform.position.z);
        Ray ray = new Ray(this.transform.position, this.transform.forward);
        RaycastHit[] hit = Physics.RaycastAll(ray, 5000);

        bool found = false;
        float distanceObst = 0;
        foreach (RaycastHit h in hit)
        {
            Debug.Log(h.transform.name);

            int layer = h.transform.gameObject.layer;
            if(layer == Const.LAYER_CONE_END || layer == Const.LAYER_CONE_START || layer == Const.LAYER_GROUND)
                continue;

            distanceObst = Vector3.Distance(this.transform.position, new Vector3(h.transform.position.x, this.transform.position.y, h.transform.position.z));
            if (h.transform.name == trap.name)
            {
                
                found = true;
                break;
            }
            else
                break;
        }

        if (distanceObst > distanceTrap)
        {
            found = true;
        }

        if (!found )
        {
            Debug.Log("Niot FOunt");
            this.transform.rotation = orient;
            return;
        }
        
        status = Const.ENEMY_STATUS.SHOWING_TRAP;

        float timeAnim = this.animation["Move"].time;
        this.animation.Stop();

        

        StartCoroutine(DeleteTrap(trap, timeAnim));
    }

    IEnumerator DeleteTrap(GameObject go, float timeAnim)
    {
        yield return new WaitForSeconds(Const.TIME_ENEMY_SHOW_TRAP);

        Destroy(go);

        this.animation.Play("Move");
        this.animation["Move"].time = timeAnim;
		if(status == Const.ENEMY_STATUS.SHOWING_TRAP)
			status = Const.ENEMY_STATUS.FOLLOWING_PATH;
    }
}

